﻿namespace DomainServices.Tools.SharedTypes
{
    using System;
    using System.Linq;
    using System.Reflection;
    using System.Runtime.CompilerServices;

    internal class CodeMemberKey
    {
        internal static CodeMemberKey CreateMethodKey(System.Reflection.MethodBase methodBase)
        {
            string[] parameterTypeNames = (from p in methodBase.GetParameters() select p.ParameterType.AssemblyQualifiedName).ToArray<string>();
            return CreateMethodKey(methodBase.DeclaringType.AssemblyQualifiedName, methodBase.Name, parameterTypeNames);
        }

        internal static CodeMemberKey CreateMethodKey(string typeName, string methodName, string[] parameterTypeNames)
        {
            return new CodeMemberKey { KeyKind = CodeMemberKeyKind.MethodKey, TypeName = typeName, MemberName = methodName, ParameterTypeNames = parameterTypeNames };
        }

        internal static CodeMemberKey CreatePropertyKey(System.Reflection.PropertyInfo propertyInfo)
        {
            return CreatePropertyKey(propertyInfo.DeclaringType.AssemblyQualifiedName, propertyInfo.Name);
        }

        internal static CodeMemberKey CreatePropertyKey(string typeName, string propertyName)
        {
            return new CodeMemberKey { KeyKind = CodeMemberKeyKind.PropertyKey, TypeName = typeName, MemberName = propertyName };
        }

        internal static CodeMemberKey CreateTypeKey(string typeName)
        {
            return new CodeMemberKey { KeyKind = CodeMemberKeyKind.TypeKey, TypeName = typeName };
        }

        internal static CodeMemberKey CreateTypeKey(System.Type type)
        {
            return CreateTypeKey(type.AssemblyQualifiedName);
        }

        public override bool Equals(object obj)
        {
            CodeMemberKey objA = obj as CodeMemberKey;
            if (object.ReferenceEquals(objA, null))
            {
                return false;
            }
            if (!object.ReferenceEquals(this, objA))
            {
                if (((this.KeyKind != objA.KeyKind) || !string.Equals(this.TypeName, objA.TypeName, StringComparison.Ordinal)) || !string.Equals(this.MemberName, objA.MemberName, StringComparison.Ordinal))
                {
                    return false;
                }
                int num = (this.ParameterTypeNames == null) ? 0 : this.ParameterTypeNames.Length;
                int num2 = (objA.ParameterTypeNames == null) ? 0 : objA.ParameterTypeNames.Length;
                if (num != num2)
                {
                    return false;
                }
                for (int i = 0; i < num; i++)
                {
                    if (!string.Equals(this.ParameterTypeNames[i], objA.ParameterTypeNames[i], StringComparison.Ordinal))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        public override int GetHashCode()
        {
            int num = (this.KeyKind.GetHashCode() ^ ((this.TypeName == null) ? 0 : this.TypeName.GetHashCode())) ^ ((this.MemberName == null) ? 0 : this.MemberName.GetHashCode());
            if (this.ParameterTypeNames != null)
            {
                foreach (string str in this.ParameterTypeNames)
                {
                    num ^= (str == null) ? 0 : str.GetHashCode();
                }
            }
            return num;
        }

        internal bool IsConstructor
        {
            get
            {
                return ((this.KeyKind == CodeMemberKeyKind.MethodKey) && string.Equals(".ctor", this.MemberName, StringComparison.OrdinalIgnoreCase));
            }
        }

        internal CodeMemberKeyKind KeyKind { get; set; }

        internal string MemberName { get; set; }

        internal System.Reflection.MethodBase MethodBase
        {
            get
            {
                System.Reflection.MethodBase method = null;
                System.Type type = this.Type;
                if (type != null)
                {
                    System.Type[] parameterTypes = this.ParameterTypes;
                    if (parameterTypes != null)
                    {
                        method = type.GetMethod(this.MemberName, parameterTypes);
                        if (method == null)
                        {
                            method = type.GetConstructor(parameterTypes);
                        }
                    }
                }
                return method;
            }
        }

        internal string MethodName { get; set; }

        internal string[] ParameterTypeNames { get; set; }

        internal System.Type[] ParameterTypes
        {
            get
            {
                System.Type[] typeArray = (this.ParameterTypeNames != null) ? (from s in this.ParameterTypeNames select System.Type.GetType(s, false)).ToArray<System.Type>() : new System.Type[0];
                if (!Enumerable.Any<System.Type>(typeArray, t => t == null))
                {
                    return typeArray;
                }
                return null;
            }
        }

        internal System.Reflection.PropertyInfo PropertyInfo
        {
            get
            {
                System.Reflection.PropertyInfo property = null;
                System.Type type = this.Type;
                if (type != null)
                {
                    property = type.GetProperty(this.MemberName);
                }
                return property;
            }
        }

        internal System.Type Type
        {
            get
            {
                return System.Type.GetType(this.TypeName, false);
            }
        }

        internal string TypeName { get; set; }

        internal enum CodeMemberKeyKind
        {
            TypeKey,
            PropertyKey,
            MethodKey
        }
    }
}

